import { action, observable } from "mobx";
import { WeaTools, WeaLocaleProvider } from 'ecCom'
import { each } from 'lodash';
import QuickTableStore from "./excel/QuickTableStore";
import CellType from './excel/celltypes';
import FormulaAPI from '../apis/formula';
import API from '../apis/excel';
import { register, setRightMenu } from './excel/command';
import getFont from '../utils/getFont';
import getCellName from '../utils/getCellName';
import * as TopActions from './excel/action/top';
import * as CommonAction from './excel/action/common';
import MenuAction from './excel/action/menu';
import AddSelectOptionsStore from './dialog/addSelectOptionsStore';
import AddFixphareStore from './dialog/addFixphareStore';
import AddSelectTreeStore from './dialog/addSelectTreeStore'
import TemplateBrowserStore from "./dialog/templateBrowserStore";
import DataSourceDialogStore from "./dialog/DataSourceDialogStore";
import AceEditorDialogStore from "./dialog/AceEditorDialogStore";
import CodeEditorDialogStore from "./dialog/CodeEditorDialogStore";
import { loadPageDs, loadPageFieldAssign } from "../apis/dataset";
import FieldPropsStore from "./excel/FieldPropsStore";
import { FieldPropsType } from "../constants/excel";
import CustomFunction from "./excel/function/CustomFunction";
import ConditionDialogStore from "./dialog/ConditionDialogStore";
import FieldAssignDialogStore from "./dialog/FieldAssignDialogStore";
const getLabel = WeaLocaleProvider.getLabel;

export default class ExcelDesignerStore {
    @observable isInit = false;
    @observable loading = false;
    @observable workbook;
    @observable readonly = false;
    appid = '';
    @observable activeCellStyle = {};
    @observable activeCellName = '';

    // quick table
    @observable quickTableVisible = false;
    @observable quickTableStore;
    @observable templateBrowserStore = new TemplateBrowserStore("excel");
    @observable disabledSignFields = true;
    @observable clearFieldDisabled = false;
    @observable deleteTableDisabled = true;
    @observable setFieldTypeDisabled = false;
    @observable isAutoFillin = false;
    @observable isAutoFillinDisabled = true;
    @observable browserAutoFillin;
    @observable nodetailJson = new Map();

    @observable dataSourceList = [];
    @observable dataSourceStore = new DataSourceDialogStore();
    @observable aceEditorStore = new AceEditorDialogStore(this);
    @observable codeEditorStore = new CodeEditorDialogStore();
    @observable fieldAssignStore = new FieldAssignDialogStore();
    @observable fieldProps;
    @observable selection = '1*1';
    @observable undoDisabled = true;
    @observable redoDisabled = true;
    @observable rowControl = {};
    @observable conditionDialogStore = new ConditionDialogStore();//条件参数
    @observable fieldAssignList = [];
    @observable detailSelectCellTypesMap = {};
    @observable detailSelectCellTypeValueMap = {};
    @observable mainSelectCellTypesMap = {};
    @observable mainSelectCellTypeValueMap = {};

    constructor() {
        this.addSelectOptionsStore = new AddSelectOptionsStore(this);
        this.addSelectTreeStore = new AddSelectTreeStore();
        this.addFixphareStore = new AddFixphareStore();
        this.templateBrowserStore.title = getLabel('503348', '选择Excel模板');
        each({ ...CommonAction }, (value, key) => {
            if (typeof value === 'function') {
                this[key] = action(value.bind(this));
            } else {
                this[key] = value;
            }
        });
        each({ ...TopActions }, (value, key) => {
            this[key] = action(value.bind(this));
        });
        each({ ...MenuAction }, (value, key) => {
            this[key] = action(value.bind(this));
        });

        this.aceEditorStore.parent = () => this;
        //  this.fieldProps.parent = () => this;
        this.fieldAssignStore.parent = () => this;
    }

    @action
    loadWorkbook = (readonly) => {
        this.isInit = true;
        this.readonly = readonly;
        this.quickTableStore = new QuickTableStore(this);
    }
    @action loadDataSourceList = (id) => {
        if(id){
            loadPageDs(id).then(list => {
                this.dataSourceList = list;
                if (this.workbook) {
                    this.reEnterCell();
                }
            });
        } else {
            this.dataSourceList = [];
        }
    }
    @action loadPageFieldAssignList = (id) => {
        if(id){
            loadPageFieldAssign(id).then(list => {
                this.fieldAssignList = list;
                if (this.workbook) {
                    this.reEnterCell();
                }
            });
        } else {
            this.fieldAssignList = [];
        }
    }
    @action
    initWorkbook = (workbook) => {
        if (!workbook) {
            return;
        }
        this.workbook = workbook;
        window.workbookInstance = workbook;
        this.workbook.suspendPaint();
        this.workbook.sheets.forEach(sheet => {
            if (sheet.getColumnCount() < 50) {
                sheet.setColumnCount(50);
            }
            if (sheet.getRowCount() < 200) {
                sheet.setRowCount(200);
            }
        });
        this.workbook.resumePaint();
    }
    @action
    showPageById = (id) => {

        if (id) {
            this.loading = true;
            Promise.all(
                [API.pageInfo(id),
                FormulaAPI.loadFormula(id)]
            ).then(([page, list]) => {
                this.aceEditorStore.formulaList = list;
                this.showPage(page);
            })
            this.dataSourceStore.reloadPageDsList = this.loadDataSourceList.bind(this, id);
            this.fieldAssignStore.reloadPageFieldAssignList = this.loadPageFieldAssignList.bind(this, id);
            this.loadDataSourceList(id);
            this.loadPageFieldAssignList(id);
        } else {
            this.showPage({ json: {} });
        }
    }

    @action
    newPage = () => {
        this.showPage({ json: {} });
        // 新建模板，将临时模板置空
        this.templateJSON = null;
    }

    reloadHeadTabs = (page) => {
        this.parent().getExcelPages(page, this.appid);
    }

    destoryWorkbook = () => {

        this.workbook = undefined;
    }
    @action
    showPage = (page) => {
        this.fieldProps = new FieldPropsStore();
        this.fieldProps.parent = () => this;
        this.conditionDialogStore.parent = () => this;
        if (typeof (page.rowControl) != 'undefined') {
            this.rowControl = JSON.parse(page.rowControl);
        }
        this.dataSourceStore.reloadPageDsList = this.loadDataSourceList.bind(this, page.id);
        this.fieldAssignStore.reloadPageFieldAssignList = this.loadPageFieldAssignList.bind(this, page.id);
        this.loadDataSourceList(page.id);
        this.loadPageFieldAssignList(page.id);
        this.codeEditorStore.currentPageId = page.id;
        this.aceEditorStore.currentPageId = page.id;
        this.page = page;
        this.labels = page.labels || {};
        this.fieldName = page.fieldName || {};
        if (this.page && this.page.id) {
            this.disabledSignFields = true;
        } else {
            this.disabledSignFields = false;
        }

        if (!this.workbook) {
            setTimeout(() => {
                this.showPage(page);
            }, 50);
            return;
        }
        const doAfters = this.loadFormula();
        const FieldCellType = CellType('FieldCellType');
        window.FieldCellType = FieldCellType;
        const NoFieldCellType = window.NoFieldCellType = CellType('NoFieldCellType');
        this.workbook.suspendPaint();
        const json = typeof page.json === 'string' ? JSON.parse(page.json) : page.json;
        this.workbook.fromJSON(json, false);

        this.workbook.sheets.forEach(sheet => {
            if (sheet.getColumnCount() < 50) {
                sheet.setColumnCount(50);
            }
            if (sheet.getRowCount() < 200) {
                sheet.setRowCount(200);
            }
            sheet.tables.all().forEach(table => {
                table.filterButtonVisible(false);
            });
        });
        this.workbook.bind(GC.Spread.Sheets.Events.EnterCell, this.enterCell);
        this.workbook.bind(GC.Spread.Sheets.Events.SheetNameChanged, this.sheetNameChanged);
        this.workbook.bind(GC.Spread.Sheets.Events.SelectionChanging, this.selectionChanging);
        register(this.workbook.commandManager());
        this.storeMenuData = [...this.workbook.contextMenu.menuData];
        this.reEnterCell();
        this.workbook.resumePaint();
        this.loading = false;
        doAfters.forEach(after => {
            after();
        })
        const activeSheet = this.workbook.getActiveSheet();
        const newSelections = activeSheet.getSelections();
        this.selectionChanging('', { newSelections });

        if (JSON.stringify(page.json) != "{}") {
            this.templateJSON = this.workbook.toJSON();
        }
        this.getSelectCelltypes();
    }


    @action
    loadFormula = (list = this.aceEditorStore.formulaList) => {
        this.workbook.clearCustomFunctions();
        if (list) {
            return list.map(obj => {
                const TempFunction = CustomFunction(obj);
                return () => {
                    const func = new TempFunction(
                        obj.name, 0, 0, { name: obj.name, description: obj.describes }
                    );
                    this.workbook.addCustomFunction(func);
                };
            });
        }
        return [];
    }

    @action
    reEnterCell = () => {
        const sheet = this.workbook.getActiveSheet();
        const sheetName = sheet.name();
        const col = sheet.getActiveColumnIndex();
        const row = sheet.getActiveRowIndex();

        this.enterCell({}, {
            col,
            row,
            sheet,
            sheetName,
        });
    }

    @action
    getSelectCelltypes = () => {
        this.detailSelectCellTypeValueMap = {};
        this.detailSelectCellTypesMap = {};
        this.mainSelectCellTypeValueMap = {};
        this.mainSelectCellTypesMap = {};
        this.workbook.sheets.forEach(sheet => {
            // 明细表
            sheet.tables.all().forEach(table => {
                const bindingPath = table.bindingPath();
                if (bindingPath) {
                    const { col, colCount, row, rowCount } = table.dataRange();
                    for (let i = 0; i < colCount; i++) {
                        const cell = sheet.getCell(row, (col + i));
                        const cellType = cell.cellType();
                        if (cellType && cellType.getCellTypeName() == 'select' && cellType.fieldType && cellType.fieldType[2].datas) {
                            const fieldName = table.getColumnDataField(i);
                            if (!this.detailSelectCellTypeValueMap[bindingPath]) {
                                this.detailSelectCellTypeValueMap[bindingPath] = {};
                            }
                            this.detailSelectCellTypeValueMap[bindingPath][fieldName] = cellType.fieldType[2].datas.map(r => ({
                                key: r.selectName,
                                showname: r.selectName
                            }))

                            if (!this.detailSelectCellTypesMap[bindingPath]) {
                                this.detailSelectCellTypesMap[bindingPath] = [];

                            }
                            this.detailSelectCellTypesMap[bindingPath].push({
                                key: fieldName,
                                showname: cellType.label
                            })
                        }
                    }
                }

            });

            const { data } = sheet.toJSON();
            if (data) {
                const { dataTable } = data;
                if (dataTable) {
                    each(dataTable, (o, rowIndex) => {
                        each(o, (obj, colIndex) => {
                            const bindingPath = sheet.getBindingPath(rowIndex, colIndex);
                            if (bindingPath) {

                                const [sheetName, fieldName] = bindingPath.split('.');
                                const cell = sheet.getCell(rowIndex, colIndex);
                                const cellType = cell.cellType();
                                if (cellType && cellType.getCellTypeName() == 'select' && cellType.fieldType && cellType.fieldType[2].datas) {
                                    if (!this.mainSelectCellTypeValueMap[sheetName]) {
                                        this.mainSelectCellTypeValueMap[sheetName] = {};
                                    }
                                    this.mainSelectCellTypeValueMap[sheetName][fieldName] = cellType.fieldType[2].datas.map(r => ({
                                        key: r.selectName,
                                        showname: r.selectName
                                    }))

                                    if (!this.mainSelectCellTypesMap[sheetName]) {
                                        this.mainSelectCellTypesMap[sheetName] = [];

                                    }
                                    this.mainSelectCellTypesMap[sheetName].push({
                                        key: fieldName,
                                        showname: cellType.label
                                    })
                                }
                            }

                        });
                    });

                }
            }
        });
    }

    @action sheetNameChanged = (e, info) => {
        const { sheet, newValue, oldValue } = info;
        const { data } = sheet.toJSON();
        if (data) {
            const { dataTable } = data;
            if (dataTable) {
                console.log(dataTable);
                each(dataTable, (o, rowIndex) => {
                    each(o, (obj, colIndex) => {
                        const bindingPath = sheet.getBindingPath(rowIndex, colIndex);
                        if (bindingPath) {
                            const [sheetName, fieldName] = bindingPath.split('.');
                            if (sheetName === oldValue) {
                                sheet.setBindingPath(rowIndex, colIndex, `${newValue}.${fieldName}`);
                            }
                        }

                    });
                });

            }
        }

        sheet.tables.all().forEach(table => {
            const bindingPath = table.bindingPath();
            if (bindingPath) {
                const paths = bindingPath.split('.');
                paths[0] = newValue;
                table.bindingPath(paths.join('.'));
            }
        });
        // const rowCount = sheet.getRowCount();
        // const colCount = sheet.getColumnCount();
        // for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
        //     for (let colIndex = 0; colIndex < colCount; colIndex++) {
        //         const bindingPath = sheet.getBindingPath(rowIndex, colIndex);
        //         if(bindingPath) {
        //             const [sheetName, fieldName] = bindingPath.split('.');
        //             if (sheetName === oldValue) {
        //                 sheet.setBindingPath(rowIndex, colIndex, `${newValue}.${fieldName}`);
        //             }
        //         }
        //     }
        // }
        // sheet名变化，下拉款关系数据也需要变化
        this.getSelectCelltypes();
    }
    @action selectionChanging = (e, info) => {
        const { newSelections } = info;
        const selection = newSelections[0];
        this.selection = `${selection.rowCount}*${selection.colCount}`
    }
    @action
    enterCell = (e, info) => {
        const { row, col, sheet } = info;
        const range = sheet.getCell(row, col);
        const cellType = range.cellType();
        // const rowControl =this.rowControl;
        let cellTypeName = undefined;
        const FieldCellType = CellType('FieldCellType');
        const isField = cellType instanceof FieldCellType;
        let showname = '';
        let fieldtype = "";
        let field = "";
        if (isField) {
            cellTypeName = cellType.getCellTypeName();
        }
        const undoManager = this.workbook.undoManager();
        this.undoDisabled = !undoManager.canUndo();
        this.redoDisabled = !undoManager.canRedo();
        const font = range.font();
        const vAlign = range.vAlign();
        const hAlign = range.hAlign();
        const underline = range.textDecoration();
        const fontObj = getFont(font);
        const table = sheet.tables.find(row, col);
        this.activeCellStyle = {
            bold: fontObj.fontWeight === 'bold',
            fontFamily: fontObj.fontFamily,
            fontSize: fontObj.fontSize,
            hAlign,
            italic: fontObj.fontStyle === 'italic',
            spanCell: !!info.sheet.getSpan(range.row, range.col),
            underline: underline === GC.Spread.Sheets.TextDecorationType.underline,
            vAlign,
            wordwrap: range.wordWrap(),
            cellTypeName,
            combineSameCell: !!(isField && table && cellType.combineSameCell),
            combineSameCellDisabled: !(isField && table),
        };
        this.isAutoFillinDisabled = true;
        if (isField && (cellTypeName === 'select' || (cellTypeName.indexOf('browser') == 0 && cellTypeName != 'browser290'))) {
            this.isAutoFillinDisabled = false;
            this.isAutoFillin = !!cellType.autoFillin;
        }
        this.setFieldTypeDisabled = false;
        let currentSingleCell;
        if (table) {
            setRightMenu(this, true, row <= table.dataRange().row);
            this.activeCellName = `${getCellName(range.row, range.col)}(${table.name()})`;
            this.clearFieldDisabled = true;
            this.deleteTableDisabled = false;
            currentSingleCell = sheet.getCell(table.dataRange().row, col);
        } else {
            setRightMenu(this, false);
            this.activeCellName = getCellName(range.row, range.col);
            this.clearFieldDisabled = false;
            this.deleteTableDisabled = true;
            currentSingleCell = range;
        }
        const fillinArea = false;
        if (this.fieldProps) {
            const fieldPropsType = table ? FieldPropsType.Detail : fillinArea ? FieldPropsType.FillinArea : FieldPropsType.Main;
            this.fieldProps.initProps(this.dataSourceList, range, table, this.rowControl);
        }

        if (this.fieldAssignStore) {
            const sheetName = sheet.name();
            const currentCellType = currentSingleCell.cellType();
            const isCurrentField = currentCellType instanceof FieldCellType;
            if (isCurrentField) {
                //点击字段，保存字段属性，fieldtype：mainfield/detailfield/cellfield,showname,field
                const { detailIndex, detailName, fieldName } = currentCellType;
                // showname = sheetName+'.'+cellType.detailName();
                showname = `${sheetName}.${detailName}.${fieldName}`;

                if (detailIndex) {
                    fieldtype = 'detailfield';
                    field = `${sheetName}.detail_${detailIndex}.${fieldName}`;
                } else {
                    fieldtype = 'mainfield';
                    field = `${sheetName}.${fieldName}`;
                }
            } else {
                fieldtype = 'cellfield';
                showname = `${sheetName}.${getCellName(range.row, range.col)}`;
            }
            const { visible } = this.fieldAssignStore;
            if (visible) {
                console.log("this.fieldAssignStore", this.fieldAssignStore);
                console.log("this.fieldAssignStore", this.fieldAssignStore.datas);
                const { text, record, index, onEdit } = this.tableCellProps;
                onEdit({
                    type: "CUSTOM",
                    record: {
                        ...record,
                        showname: showname,
                        fieldtype: fieldtype,
                        field: field
                    },
                    index,
                    key: "customrender",
                    value: 1
                });
            }
        }
    }
    undo = () => {
        this.workbook.undoManager().undo();
        this.reEnterCell();
    }
    redo = () => {
        this.workbook.undoManager().redo();
        this.reEnterCell();
    }
}